package com.example.sourcecodelearning.modules.statemachine.config;

import com.example.sourcecodelearning.modules.statemachine.Event;
import com.example.sourcecodelearning.modules.statemachine.States;
import com.example.sourcecodelearning.modules.statemachine.listener.BasketballMusicStateMachineEventListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;

import java.util.EnumSet;

@Configuration
@EnableStateMachine
public class BasketballMusicStateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Event> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Event> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
                .listener(new BasketballMusicStateMachineEventListener()); // 设置状态机事件监听器
    }

    // 配置状态机的初始状态和所有可能的状态
    @Override
    public void configure(StateMachineStateConfigurer<States, Event> states) throws Exception {
        states.withStates()
                // 初始状态
                .initial(States.IDLE)
                .states(EnumSet.allOf(States.class));
    }

    // 配置状态机的状态转换规则
    @Override
    public void configure(StateMachineTransitionConfigurer<States, Event> transitions) throws Exception {
        transitions.withExternal()
                // 从IDLE状态，通过触发START_BB_MUSIC事件，转换到PLAYING_BB状态。
                .source(States.IDLE).target(States.PLAYING_BB).event(Event.START_BB_MUSIC)
                .and()
                .withExternal()
                .source(States.PLAYING_BB).target(States.SINGING).event(Event.STOP_BB_MUSIC)
                .and()
                .withExternal()
                .source(States.SINGING).target(States.PLAYING_BB).event(Event.START_BB_MUSIC);
    }
}
